/*
 * ArithmeticParser.cpp
 *
 *  Created on: 27.05.2012
 *      Author: ignacio
 */


#include "ArithmeticParser.h"
using std::cout;
using std::endl;
#include <set>
using std::set;
using std::pair;

#include <algorithm>
using std::copy;
using std::find;
using std::random_shuffle;
#include <csignal>
using std::signal;

namespace neurignacio{


inline int Addition::operator()(Node* x, Node* y)
{
	return x->eval() + y->eval();
}

int Substraction::operator()(Node* x, Node* y)
{
	return x->eval() - y->eval();
}

inline int Multiplication::operator()(Node* x, Node* y)
{
	return x->eval() * y->eval();
}

inline int Division::operator()(Node* x, Node* y)
{
	int evalX=x->eval();
	int evalY=y->eval();
	if (evalY)
		return (evalX % evalY == 0? evalX / evalY : 0);
	else
		return 0;
}

string Node::print()
{
	ostringstream oss;
	oss << this->info();
	oss << " (&" << this <<")";
	oss << ", p=";
	if (this->p)
		oss << *this->p;
	else
		oss << "?";
	oss << " (&" << this->p<<")";
	oss << ", left=";
	if (this->left)
			oss << *this->left;
		else
			oss << "?";
	oss << " (&" << this->left<<")";
	oss << ", right=";
	if (this->right)
			oss << *this->right;
		else
			oss << "?";
	oss << " (&" << this->right<<")";
	return oss.str();
}

string OperatorNode::print()
{
	ostringstream oss;
	oss << Node::print();
	oss << ", operation=";
	if (this->operation)
		oss << *this->operation;
	else
		oss << "?";
	oss << " (&" << this->operation << ")";
	return oss.str();
}

string NumberNode::print()
{
	ostringstream oss;
	oss << Node::print();
	oss << ", number=";
	if (this->number)
		oss << *this->number;
	else
		oss << "?";
	oss << " (&" << this->number << ")";
	return oss.str();
}
//

Node Tree::SENTINEL=Node();
Node* Tree::nil=&SENTINEL;
Tree::Tree(void)
{
	nil->left=&SENTINEL;
	nil->right=&SENTINEL;
	nil->p=&SENTINEL;
	root=nil;

}

Tree::~Tree()
{

}


void Tree::inorderTreeWalk(Node* x) const
{
	ostringstream out;
    if (x!=this->nil)
    {
    	cout << "(";
        inorderTreeWalk(x->left);
        cout << *x;
        inorderTreeWalk(x->right);
        cout << ")";
    }
}

double fitScore(const int value, const int goal)
{
	int diff = goal-value;
	diff = (diff>0? diff : -diff);

	return static_cast<double>(1)/(diff+1);
}

} // end namespace neurignacio

